package com.shuidihuzhu.sdb.helper.log.matter;

import com.shuidihuzhu.sdb.helper.log.LogFur;
import com.shuidihuzhu.sdb.helper.log.annotation.LogTrace;
import com.shuidihuzhu.sdb.helper.log.config.LogConfig;
import com.shuidihuzhu.sdb.helper.log.config.LogConfigDefault;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * 日志追踪
 */
@Slf4j
public class LogTraceMatter implements LogFur<LogTrace> {
    @Override
    public void before(Method method, Object param, LogTrace annotation) {
        if (annotation == null || method == null) {
            return;
        }
        final String mdcKey = mdcKey(annotation);
        final String keyWords = keyWords(method, param, annotation);
        if (StringUtils.hasText(keyWords)) {
            MDC.put(mdcKey, keyWords);
        }
    }

    @Override
    public void after(Method method, Object result, LogTrace annotation) {
        if (annotation == null) {
            return;
        }
        final String mdcKey = mdcKey(annotation);
        log.debug("日志追踪设置的mdc信息，key:{}, value:{}", mdcKey, MDC.get(mdcKey));
        MDC.remove(mdcKey);
    }

    /**
     * 获取mdc key
     */
    private String mdcKey(LogTrace lt) {
        if (StringUtils.hasText(lt.mdcKey())) {
            return lt.mdcKey();
        }
        if (StringUtils.hasText(LogConfig.getMdcKey())) {
            return LogConfig.getMdcKey();
        }
        return LogConfigDefault.MDC_KEY_DEFAULT;
    }

    @Override
    public Class<LogTrace> getType() {
        return LogTrace.class;
    }

    /**
     * 获取关键字
     * @return
     */
    private String keyWords(Method method, Object param, LogTrace lt) {
        if (lt == null || !StringUtils.hasText(lt.key())) {
            if (method == null) {
                return null;
            }
            return String.join(" ", method.getDeclaringClass().getSimpleName(), method.getName());
        }
        if (param == null) {
            return lt.key();
        }

        // el 解析
        final Expression expression = new SpelExpressionParser().parseExpression(lt.key());
        final EvaluationContext context = new StandardEvaluationContext();

        context.setVariable("p", param);
        if (param.getClass().isArray()) {
            Object[] arr = (Object[]) param;
            if (arr.length == 1) {
                context.setVariable("p", arr[0]);
            }
        }
        return expression.getValue(context, String.class);
    }
}
